<script setup lang="ts">
  import { ref, useSlots, watch, computed } from 'vue'
  import { ElInput, ElButton, ElScrollbar, ElResult, ElEmpty, ElPagination } from 'element-plus'
  import { IconType, IconsType, SGridAutoFillCols, SIcon } from '@xtail/vue3'
  import Search from '@iconify-icons/tabler/search'
  import { IconSetPropsType } from './types'

  defineOptions({
    name: 'XIconSet'
  })

  const props = withDefaults(defineProps<IconSetPropsType>(), {
    icons: [] as any,
    size: 'default',
    filter: true,
    filterIptProps: {} as any,
    filterBtnProps: {} as any,
    filterClass: '',
    filterStyle: '',
    scrollbarProps: {} as any,
    gridAutoFillColsProps: {} as any,
    iconBtnProps: {} as any,
    iconBtnSelectedProps: {} as any,
    iconClass: '',
    iconStyle: '',
    iconSelectedClass: '',
    iconSelectedStyle: '',
    pagination: true,
    defaultPageSize: 50,
    paginationProps: {} as any,
    paginationScrollbarProps: {} as any,
    paginationScrollbarClass: '',
    paginationScrollbarStyle: '',
    emptyProps: {} as any
  })

  const value = defineModel<IconType>({ default: null })

  const slots = useSlots()

  const filterKey = ref('')
  const iconsFiltered = ref<IconsType>([])
  const filterIcon = () => {
    if (filterKey.value.trim() === '') iconsFiltered.value = props.icons
    iconsFiltered.value = props.icons.filter(icon => icon?.iconName?.includes(filterKey.value))
  }
  watch(
    () => props.icons,
    () => filterIcon(),
    { immediate: true, deep: true }
  )

  const total = computed(() => iconsFiltered.value.length)
  const pageSize = ref(props.defaultPageSize)
  const pageCount = computed(() => {
    if (!props.pagination) return 1
    return Math.ceil(total.value / pageSize.value)
  })
  const currentPage = ref(1)
  const currentPageIcons = computed(() => {
    if (!props.pagination) return iconsFiltered.value
    return iconsFiltered.value.slice(
      (currentPage.value - 1) * pageSize.value,
      currentPage.value * pageSize.value
    )
  })
</script>

<template>
  <div class="x-icon-set">
    <div v-if="filter" class="x-icon-set__filter" :class="filterClass" :style="filterStyle">
      <el-input
        v-bind="{
          ...filterIptProps,
          size: filterIptProps.size ?? size,
          placeholder: filterIptProps.placeholder ?? '过滤图标...',
          clearable: true
        }"
        v-model.trim="filterKey"
        @keydown.enter="filterIcon"
      >
        <template v-if="slots['filter-ipt-prefix']" #prefix>
          <slot name="filter-ipt-prefix" />
        </template>
        <template v-if="slots['filter-ipt-suffix']" #suffix>
          <slot name="filter-ipt-suffix" />
        </template>
        <template v-if="slots['filter-ipt-prepend']" #prepend>
          <slot name="filter-ipt-prepend" />
        </template>
        <template v-if="slots['filter-ipt-append']" #append>
          <slot name="filter-ipt-append" />
        </template>
      </el-input>
      <el-button
        v-bind="{
          ...filterBtnProps,
          size: filterBtnProps.size ?? size,
          plain: filterBtnProps.plain ?? true,
          type: filterBtnProps.type ?? 'primary'
        }"
        @click="filterIcon"
      >
        <template #icon>
          <slot name="filter-btn-icon">
            <s-icon :icon-props="{ icon: Search }" />
          </slot>
        </template>
      </el-button>
    </div>
    <el-scrollbar v-bind="{ ...scrollbarProps, height: scrollbarProps.height ?? '100px' }">
      <el-result v-if="resultProps" v-bind="resultProps">
        <template v-if="slots['result-icon']" #icon>
          <slot name="result-icon" />
        </template>
        <template v-if="slots['result-title']" #title>
          <slot name="result-title" />
        </template>
        <template v-if="slots['result-sub-title']" #sub-title>
          <slot name="result-sub-title" />
        </template>
        <template v-if="slots['result-extra']" #extra>
          <slot name="result-extra" />
        </template>
      </el-result>
      <el-empty
        v-else-if="iconsFiltered.length === 0"
        v-bind="{ ...emptyProps, description: emptyProps.description ?? '当前图标列表为空' }"
      >
        <template v-if="slots['empty-bottom']" #default>
          <slot name="empty-bottom" />
        </template>
        <template v-if="slots['empty-image']" #image>
          <slot name="empty-image" />
        </template>
        <template v-if="slots['empty-description']" #description>
          <slot name="empty-description" />
        </template>
      </el-empty>
      <s-grid-auto-fill-cols
        v-else
        v-bind="{
          ...gridAutoFillColsProps,
          colMinWidth: gridAutoFillColsProps.colMinWidth ?? '3.05rem',
          rowGap: gridAutoFillColsProps.rowGap ?? '0.25rem'
        }"
      >
        <el-button
          v-for="(icon, index) in currentPageIcons"
          :key="index"
          v-bind="
            value?.iconName === icon?.iconName
              ? {
                  ...iconBtnSelectedProps,
                  size: iconBtnSelectedProps.size ?? size,
                  plain: iconBtnSelectedProps.plain ?? true,
                  type: iconBtnSelectedProps.type ?? 'primary'
                }
              : {
                  ...iconBtnProps,
                  size: iconBtnProps.size ?? size,
                  plain: iconBtnProps.plain ?? true
                }
          "
          @click="() => (value = icon)"
        >
          <template #icon>
            <div
              :class="
                value?.iconName === icon?.iconName ? iconSelectedClass || iconClass : iconClass
              "
              :style="
                value?.iconName === icon?.iconName ? iconSelectedStyle || iconStyle : iconStyle
              "
            >
              <s-icon :icon-type="icon?.iconType" :icon-props="icon?.iconProps" />
            </div>
          </template>
        </el-button>
      </s-grid-auto-fill-cols>
    </el-scrollbar>
    <el-scrollbar
      v-if="pagination"
      v-bind="paginationScrollbarProps"
      class="x-icon-set__pagination-container"
      :class="paginationScrollbarClass"
      :style="paginationScrollbarStyle"
    >
      <el-pagination
        v-bind="{
          ...paginationProps,
          size: paginationProps.size ?? size,
          layout: paginationProps.layout ?? 'prev, pager, next',
          total,
          pageCount
        }"
        v-model:page-size="pageSize"
        v-model:current-page="currentPage"
      />
    </el-scrollbar>
  </div>
</template>

<style lang="scss">
  @use './style' as *;
</style>
